#ifndef _ENC_HW_INTF_H__
#define _ENC_HW_INTF_H__
#include "os/types.h"
#include "bsp/bsp_drivers.h"
#if CONFIG_USE_MAG_ENCODER
#include "math/fast_math.h"

#if (CONFIG_ENCODER_TYPE == CONFIG_ENCODER_MT)
/*min. 994 hz*/
#define CONFIG_MAG_ENCOCDER_MAX_RES 4096
#define ENC_PWM_MAX_RES    4119
#define ENC_PWM_INIT_WIDTH 16 //PWM
#define ENC_PWM_ERROR_WIDTH 0
#define ENC_PWM_END_WIDTH   8
#elif (CONFIG_ENCODER_TYPE == CONFIG_ENCODER_AMS)
#define CONFIG_MAG_ENCOCDER_MAX_RES  4096
#define CONFIG_MAG_ENCOCODER_SPI_RES (1<<14)
/*min. 490 Hz, max 603 Hz*/
#define ENC_PWM_MAX_RES 4119
#define ENC_PWM_INIT_WIDTH 12 //PWM 起始宽度
#define ENC_PWM_ERROR_WIDTH 4 //PWM 指示错误的宽度
#define ENC_PWM_END_WIDTH   0
#elif (CONFIG_ENCODER_TYPE == CONFIG_ENCODER_SIMULINK)
#define CONFIG_MAG_ENCOCDER_MAX_RES 4096
#define ENC_PWM_MAX_RES 4000
#define ENC_PWM_INIT_WIDTH 0 //PWM 起始宽度
#define ENC_PWM_ERROR_WIDTH 0 //PWM 指示错误的宽度
#define ENC_PWM_END_WIDTH   0
#endif

#define enc_pwm_duty(time, period) ((float)(time)/(period))

__STATIC_INLINE float pulse_cnt_from_duty(float duty) {
	return (duty * (float)CONFIG_MAG_ENCOCDER_MAX_RES);
}

__STATIC_INLINE float angle_from_pulse_cnt(float pulse_cnt) {
	return (M_2PI/(float)CONFIG_MAG_ENCOCDER_MAX_RES * (pulse_cnt));
}

__STATIC_INLINE float mag_encoder_duty(float time, float period) {
	float pwm_duty = enc_pwm_duty(time, period);
	return (pwm_duty * ENC_PWM_MAX_RES - ENC_PWM_INIT_WIDTH)/(ENC_PWM_MAX_RES - ENC_PWM_END_WIDTH - ENC_PWM_INIT_WIDTH - ENC_PWM_ERROR_WIDTH);
};

typedef void (*init_pos_callback)(void *ctx, float pulse_cnt);
void enc_hw_intf_init(init_pos_callback cb, void *ctx);
void enc_pwm_irq_handler(float time, float period);
void enc_hw_intf_log(void);

#if CONFIG_ENCODER_SPI
#include "encoder_spi.h"
#elif CONFIG_ENCODER_PWM
#include "encoder_pwm.h"
#endif

#if (CONFIG_ENCODER_ABI)
__STATIC_INLINE float enc_count(void) {
	return (float)_enc_count();
}

__STATIC_INLINE void enc_set_count(u16 count) {
	_enc_set_count(count);
}
#elif (CONFIG_ENCODER_ABS)
__STATIC_INLINE float enc_count(void) {
	return enc_abs_count();
}

__STATIC_INLINE void enc_set_count(u16 count) {
	
}
#else
__STATIC_INLINE float enc_count(void) {
	return 0;
}

__STATIC_INLINE void enc_set_count(u16 count) {
}
#endif


#endif /* CONFIG_USE_MAG_ENCODER */
#endif /* _ENC_HW_INTF_H__ */

